package com.ruoyi.chat.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.chat.constant.RagConstants;
import com.ruoyi.chat.constant.RagFlowCode;
import com.ruoyi.chat.domain.Dataset;
import com.ruoyi.chat.exception.ragFlowReqException;
import com.ruoyi.chat.http.RagFlowUtils;
import com.ruoyi.chat.mapper.DatasetMapper;
import com.ruoyi.chat.service.IDatasetRoleService;
import com.ruoyi.chat.service.IDatasetService;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.chat.request.chat.DataSetsRequest;
import com.ruoyi.common.utils.ArraysUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 知识库信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-03-24
 */
@Service
public class DatasetServiceImpl implements IDatasetService
{

    private static final Logger log = LoggerFactory.getLogger(DatasetServiceImpl.class);

    @Autowired
    private DatasetMapper datasetMapper;

    @Autowired
    private IDatasetRoleService datasetRoleService;

    /**
     * 查询知识库信息
     * 
     * @param id 知识库信息主键
     * @return 知识库信息
     */
    @Override
    public Dataset selectDatasetById(Long id)
    {
        LoginUser user = getLoginUser();
        List<Long> roleIds = SecurityUtils.getRoleIds();
        return datasetMapper.selectDatasetById(id, user.getUserId(), roleIds);
    }


    @Override
    public List<Dataset> selectDatasetByIds(Long[] ids, Long userId, List<Long> roleIds)
    {
        return datasetMapper.selectDatasetByIds(ids, userId, roleIds);
    }

    @Override
    public Dataset selectDatasetByName(String name) {
        return datasetMapper.selectDatasetByName(name);
    }

    /**
     * 查询知识库信息列表
     * 
     * @param dataset 知识库信息
     * @return 知识库信息
     */
    @Override
    public List<Dataset> selectDatasetList(Dataset dataset)
    {
        LoginUser user = getLoginUser();
        dataset.setUserId(user.getUserId());
        List<Long> roleIds = SecurityUtils.getRoleIds();
        return datasetMapper.selectDatasetList(dataset, roleIds);
    }

    /**
     * 新增知识库信息
     * 
     * @param dataset 知识库信息
     * @return 结果
     */
    @Override
    public int insertDataset(Dataset dataset)
    {
        dataset.setCreateTime(DateUtils.getNowDate());
        return datasetMapper.insertDataset(dataset);
    }

    @Override
    @Transactional
    public int add(Dataset dataset, String url) {
        // 参数校验
        this.checkParam(dataset);

        // 本地保存知识库(先保存本地，再请求ragFlow，返回标识再更新，否则无法保证事务一致)
        dataset.setUserId(getLoginUser().getUserId());
        int rows = this.insertDataset(dataset);
        // 用户设置不共享 则无视角色关联信息
        if (RagConstants.DATA_NOT_SHOW.equals(dataset.getIsShow())) {
            return rows;
        }
        // 关联 知识库---角色
        datasetRoleService.dataRoleRelate(dataset.getId(), dataset.getRoles());

        // 请求ragFlow新增知识库
        DataSetsRequest dataSetsRequest = new DataSetsRequest();
        BeanUtils.copyProperties(dataset, dataSetsRequest);
        JSONObject postResult = RagFlowUtils.sendPost(url, JSONObject.from(dataSetsRequest));
        JSONObject successInfo = JSONObject.from(postResult.get(RagFlowCode.DATA));
        // 回填rag_dataset_id
        dataset.setRagDatasetId(String.valueOf(successInfo.get("id")));
        this.updateDataset(dataset);
        return rows;
    }

    /**
     * 修改知识库信息
     * 
     * @param dataset 知识库信息
     * @return 结果
     */
    @Override
    public int updateDataset(Dataset dataset)
    {
        dataset.setUpdateTime(DateUtils.getNowDate());
        return datasetMapper.updateDataset(dataset);
    }

    @Override
    @Transactional
    public int update(Dataset dataset, String url) {
        // 编辑前进行鉴权
        checkAuth(new Long[]{dataset.getId()});
        // 本地更新知识库信息
        int rows = updateDataset(dataset);
        // 关联 知识库---角色
        datasetRoleService.dataRoleRelate(dataset.getId(), dataset.getRoles());
        DataSetsRequest dataSetsRequest = new DataSetsRequest();
        BeanUtils.copyProperties(dataset, dataSetsRequest);
        RagFlowUtils.sendPut(url, JSONObject.from(dataSetsRequest));
        return rows;
    }

    @Override
    @Transactional
    public int delete(Long[] ids, String url) {
        // 删除前进行鉴权
        List<Dataset> datasets = checkAuth(ids);
        // 先本地删除知识库信息
        int rows = deleteDatasetByIds(ids);
        // todo 清除 知识库---角色 关联关系
        DataSetsRequest dataSetsRequest = new DataSetsRequest();
        List<String> ragDataIds = datasets.stream().map(Dataset::getRagDatasetId).collect(Collectors.toList());
        dataSetsRequest.setIds(ragDataIds);
        RagFlowUtils.sendDelete(url, JSONObject.from(dataSetsRequest));
        return rows;
    }

    @Override
    public List<Dataset> checkAuth(Long[] inputIds) {
        if (ArraysUtils.isBlank(inputIds)) {
            log.error("请先选择知识库");
            throw new ragFlowReqException("请先选择知识库");
        }
        // 先入参去重
        Long[] ids = Arrays.stream(inputIds).distinct().toArray(Long[]::new);
        List<Dataset> datasets = this.selectDatasetByIds(ids, getLoginUser().getUserId(), SecurityUtils.getRoleIds());
        if (CollectionUtils.isEmpty(datasets) || datasets.size() < ids.length) {
            log.error("知识库作者未共享，您无权操作");
            throw new ragFlowReqException("知识库作者未共享，您无权操作");
        }
        return datasets;
    }

    /**
     * 批量删除知识库信息
     * 
     * @param ids 需要删除的知识库信息主键
     * @return 结果
     */
    @Override
    public int deleteDatasetByIds(Long[] ids)
    {
        return datasetMapper.deleteDatasetByIds(ids);
    }

    /**
     * 删除知识库信息信息
     * 
     * @param id 知识库信息主键
     * @return 结果
     */
    @Override
    public int deleteDatasetById(Long id)
    {
        return datasetMapper.deleteDatasetById(id);
    }

    @Override
    public void checkParam(Dataset dataset) {
        Dataset result = datasetMapper.selectDatasetByName(dataset.getName());
        // 校验重名知识库
        if (result != null) {
            log.error("名称重复：{}", dataset.getName());
            throw new ragFlowReqException("名称重复："+dataset.getName());
        }
    }

    /**
     * 获取用户缓存信息
     */
    public LoginUser getLoginUser()
    {
        return SecurityUtils.getLoginUser();
    }
}
